﻿using CommunityToolkit.Mvvm.Input;
using DeviceController.NetCoreServer.Services;
using DeviceController.Wpf.Common;
using DeviceController.Wpf.Core;
using DeviceController.Wpf.SaveInfos;
using DeviceController.Wpf.SaveInfoServices;
using DeviceController.Wpf.ViewModels.UserManageViewModels;
using DeviceController.Wpf.Views;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Windows;
using System.Windows.Input;
using Workstation.ServiceModel.Ua;

namespace DeviceController.Wpf.ViewModels
{
    internal partial class MainWindowViewModel : SubscriptionBase
    {
        private DeviceControllerClient? _client;

        private readonly IServiceProvider _services;

        private readonly ViewContext _viewContext;

        private readonly ISaveInfoService _saveInfoService;

        public MainWindowViewModel(IServiceProvider services, ViewContext context, ISaveInfoService saveInfoService)
        {
            _viewContext = context;
            _services = services;
            OpenUserManagerCommand = new RelayCommand(OnOpenUserManager);
            ConnectCommand = new RelayCommand(OnConnect);
            CloseCommand = new RelayCommand(OnClose);
            OptenTestWindowCommand = new RelayCommand(OnOptenTestWindow);
            ThicknessChartViewModel = services.GetRequiredService<ThicknessChartViewModel>();
            TemperatureChartViewModel = services.GetRequiredService<TemperatureChartViewModel>();
            CircleDataChartViewModel = services.GetRequiredService<CircleDataChartViewModel>();
            TargetTemperatureChartViewModel = services.GetRequiredService<TargetTemperatureChartViewModel>();
            var dic = new Dictionary<string, string>
            {
                { "TestValue", "ns=4;i=2" }
            };
            base.InitializeComponent(new SubscriptionAttribute(endpointUrl: "opc.tcp://192.168.0.1:4840", 100), dic);

            ModeItemViewModels = new List<ModeItemViewModel>()
            {
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic),
                new(dic) };

            _saveInfoService = saveInfoService;
            var model = _saveInfoService.Read<AppSettingSaveInfo>();
            this.IP = model.IP;
            this.Port = model.Port;
        }

        public ICommand OpenUserManagerCommand { get; set; }

        private void OnOpenUserManager()
        {
            var window = _services.GetRequiredService<UserManageWindow>();
            window.DataContext = _services.GetRequiredService<UserManagerViewModel>();
            window.ShowDialog();
        }

        private void SaveConfigurationToLocal()
        {
            var model = _saveInfoService.Read<AppSettingSaveInfo>();

            model.IP = this.IP;
            model.Port = this.Port;

            _saveInfoService.Write(model);
        }

        public ThicknessChartViewModel ThicknessChartViewModel { get; set; }

        public TemperatureChartViewModel TemperatureChartViewModel { get; set; }

        public CircleDataChartViewModel CircleDataChartViewModel { get; set; }

        public TargetTemperatureChartViewModel TargetTemperatureChartViewModel { get; set; }

        public List<ModeItemViewModel> ModeItemViewModels { get; set; }

        private bool _testValue;

        [MonitoredItem(nodeId: "ns=4;i=2", tagName: "TestValue", samplingInterval: 100)]
        public bool TestValue
        {
            get { return _testValue; }
            set { SetProperty(ref _testValue, value); }
        }

        private string? _logMesssage;

        public string? LogMessage
        {
            get { return _logMesssage; }
            set { SetProperty(ref _logMesssage, value); }
        }

        private List<string> _logList = new List<string>();

        private const int LogCount = 30;

        private void Log(string message)
        {
            _logList.Add($"{DateTime.Now.ToString("HH:mm:ss")} " + message);

            if (_logList.Count > LogCount)
            {
                _logList.RemoveAt(0);
            }

            var builder = new StringBuilder();

            _logList.ForEach(item =>
            {
                builder.AppendLine(item);
            });

            Application.Current.Dispatcher.Invoke(() =>
            {
                LogMessage = builder.ToString();

            });
        }

        public string? SendMessage { get; set; }

        private string? _receiveMessage;

        public string? ReceiveMessage
        {
            get { return _receiveMessage; }
            set
            {
                SetProperty(ref _receiveMessage, value);
            }
        }

        private string? _connectStatus = "未连接";

        public string? ConnectStatus
        {
            get => _connectStatus;
            set => SetProperty(ref _connectStatus, value);
        }

        public ICommand? ConnectCommand { get; set; }

        private void OnConnect()
        {
            SaveConfigurationToLocal();

            if (_client?.IsConnected == true)
            {
                Log("已连接服务器！");
                return;
            }

            if (string.IsNullOrWhiteSpace(IP))
            {
                Log("请输入有效的 IP 地址！");
                return;
            }

            if (!Port.HasValue)
            {
                Log("请输入有效的端口！");
                return;
            }

            if (_client?.IsConnected == true)
            {
                _client.Disconnect();
                _client = null;
            }

            var result = Connect(IP, Port.Value);

            if (!result)
            {
                Log("连接服务器失败！");
            }
        }

        private bool Connect(string ip, int port)
        {
            if (_client?.IsConnected == true)
            {
                _client.Disconnect();
            }

            _client = new DeviceControllerClient(IPAddress.Parse(ip), port);
            _client.Connected += OnConnected;
            _client.Disconnected += OnDisconnected;
            _client.Received -= OnReceived;
            _client.Received += OnReceived;
            var result = _client.ConnectAsync();

            return result;
        }

        private void OnDisconnected(object? sender, EventArgs e)
        {
            Log("服务器连接已断开！");

            Application.Current.Dispatcher.Invoke(() =>
            {
                this.ConnectStatus = "未连接";
            });
        }

        private void OnConnected(object? sender, EventArgs e)
        {
            Log("服务器连接成功！");

            Application.Current.Dispatcher.Invoke(() =>
            {
                this.ConnectStatus = "已连接";
            });
        }

        private void OnReceived(object? sender, ReceivedEventArgs e)
        {
            var message = Encoding.UTF8.GetString(e.ReceivedData);

            try
            {
                var am = JsonSerializer.Deserialize<PartitionPackageAM>(message);

                Log("AM数据接收完成！");
                ThicknessChartViewModel.SetNewLine(am!.thickness.ToList());
            }
            catch (Exception)
            {
                Log("AM 数据接收错误！");
            }
        }

        public ICommand CloseCommand { get; set; }

        private void OnClose()
        {
            if (_client?.IsConnected != true)
            {
                Log("未连接服务器！");
                return;
            }

            _viewContext.TryGetValue<bool>("IsShowTestWindow", out var isShowTestWindow);

            if (isShowTestWindow)
            {
                Log("正在使用测试窗口！");
                return;
            }

            if (_client?.IsConnected == true)
            {
                _client.Disconnect();
                _client = null;
                ConnectStatus = "未连接";
            }
        }

        public string? IP { get; set; } = "127.0.0.1";

        public int? Port { get; set; } = 60011;

        public ICommand OptenTestWindowCommand { get; set; }

        private void OnOptenTestWindow()
        {
            _viewContext.TryGetValue<bool>("IsShowTestWindow", out var isShowTestWindow);

            if (isShowTestWindow == true)
            {
                Log("已经打开测试窗口！");
                return;
            }

            if (_client?.IsConnected == true && isShowTestWindow != true)
            {
                _viewContext.Add("TcpClient", _client);
                var view = _services.GetViewService<TestWindow, TestWindowViewModel>();
                view.Show();
            }
            else
            {
                Log("未连接服务端！");
            }
        }
    }
}
